﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------

#ifndef _UXS_SIMPLEPTR_TYPE_H
#define _UXS_SIMPLEPTR_TYPE_H

#pragma once

#include "../Defines/Defines.h"

namespace UX_STL
{
namespace UXTypes
{

	//
	// Simple Ptr
	//

#	define TSimplePtr	Ptr

	template <typename T>
	struct TSimplePtr
	{
	// types
	public:
		typedef TSimplePtr<T>	Self;
		typedef T				value_t;
		typedef T *				value_ptr_t;
		typedef bool			_is_simple_ptr;

		
	// variables
	private:
		T *	_ptr;


	// methods
	private:
		template <typename ToType, typename FromType>
		static void _CheckCast (FromType *p)
		{
			ASSERT( TypeDescriptor::CanCastTo< ToType >( p ) );
			//DESCTOP_ONLY( ASSERT( dynamic_cast< ToType *>( p ) != null ) );
		}


	public:
		TSimplePtr (): _ptr(null) {}
		
		TSimplePtr (T *p): _ptr(p) {}


		/*template <typename T2>
		Self & operator = (T2 *right)
		{
			_ptr = right;
			return *this;
		}*/


		Self & operator = (T *right)
		{
			_ptr = right;
			return *this;
		}

		/*
		template <typename T2>
		Self & operator = (TSimplePtr<T2> &right)
		{
			_ptr = right._ptr;
			return *this;
		}
		*/

		Self & operator = (Self &right)
		{
			_ptr = right._ptr;
			return *this;
		}

		
		operator T * () const
		{
			return _ptr;
		}
		

		operator T *& ()
		{
			return _ptr;
		}


		T * operator -> () const
		{
			ASSUME( _ptr != null );
			return _ptr;
		}


		T & operator * () const
		{
			ASSUME( _ptr != null );
			return *_ptr;
		}

		T ** operator & ()
		{
			return &_ptr;
		}


		T * const * operator & () const
		{
			return &_ptr;
		}


		T *& ref ()
		{
			return _ptr;
		}

		T* const & ref () const
		{
			return _ptr;
		}


		T * ptr ()
		{
			ASSERT( _ptr != null );
			return _ptr;
		}

		const T * const ptr () const
		{
			ASSERT( _ptr != null );
			return _ptr;
		}


		bool Empty () const
		{
			return ( _ptr == null );
		}

		bool IsNull () const
		{
			return ( _ptr == null );
		}

		bool IsNotNull () const
		{
			return ( _ptr != null );
		}


		void Reset ()
		{
			_ptr = null;
		}
		
		template <typename T2>
		T2 To ()
		{
			STATIC_ASSERTE( typename T2::_is_simple_ptr(true) );
			_CheckCast< typename T2::value_t, value_t >( _ptr );
			return T2( (typename T2::value_t *) _ptr );
		}
		
		/*
		template <typename B>
		bool operator == (const B *right) const
		{
			return _ptr == right;
		}

		
		bool operator == (const Self &right) const
		{
			return _ptr == right._ptr;
		}

		
		template <typename B>
		bool operator != (const B *right) const
		{
			return _ptr != right;
		}
		

		bool operator != (const Self &right) const
		{
			return _ptr != right._ptr;
		}
		*/

		bool operator > (const Self &right) const
		{
			return _ptr > right._ptr;
		}
		
		bool operator < (const Self &right) const
		{
			return _ptr < right._ptr;
		}


		bool operator ! () const
		{
			return _ptr != null;
		}

		template <typename R>
		R *			ToPtr ()	const
		{
			_CheckCast< R, value_t >( _ptr );
			return (R *)ptr();
		}
		
		template <typename R>
		R const *	ToCPtr ()	const
		{
			_CheckCast< R const, value_t >( _ptr );
			return (R const *)ptr();
		}
	};

#	undef  TSimplePtr

//-------------------------------------------------------------------

}	// UXTypes
}	// UX_STL

#endif	// _UXS_SIMPLEPTR_TYPE_H
